

texture rays_texture;             
texture land_texture;        

sampler rays = sampler_state
{
    Texture = <rays_texture>;
};

sampler landscape = sampler_state
{
    Texture = <land_texture>;
};

// -- rays computing params

float3  lookDirection;
float3  lookUp;
float3  lookRight;
float3  center;
float   radius;
float3  rayOrig;
float3  landmetric;
float3  landbase;

float   stepsize			 = 1.0f;
int		stepCount			 = 500;

float3  sphere_point( float an1, float an2 )
{
	return center + lookDirection*radius*sin(an1)*cos(an2) +
							lookUp*radius*sin(an1)*sin(an2) +
							lookRight*radius*cos(an1);
}			      

struct VSsimpleout
{
    float4 position : POSITION;   
    float2 tex		: TEXCOORD0;  
};

struct PSout
{
    float4 color : COLOR0;  
};

VSsimpleout SimpleVS( float4 pos : POSITION, float2 tex : TEXCOORD0 )
{
    VSsimpleout output;
    output.position = pos;
    output.tex = tex;
    return output;    
}

float float2_to_float( float2 vl )
{
	const float2 byte_to_float=float2(256.0,1.0/256.0)/25.0;
	return dot(vl,byte_to_float);
}

float hpi = atan(1.0)*2;

PSout RayTraycingPS( VSsimpleout px )
{
	PSout output;
	float4 angles = tex2D(rays,px.tex);
	
	float an1 = float2_to_float(angles.rg);
	float an2 = float2_to_float(angles.ba) - hpi;
	
	float3 dest = sphere_point( an1, an2 );
	float3 rayDirection = normalize(dest - rayOrig);
	
	output.color = float4(0,0,0,0);
	
	int   stepIndex = 0;
    float step = 0;
    float maxlen = length(dest - rayOrig);
    
    while (stepIndex < stepCount)
    {
		++stepIndex;
		step += stepsize;
		if (step < maxlen) 
		{
			float3 cur = rayOrig + rayDirection*step;
			float3 offset = cur - landbase;
			if ( offset.x >= 0 && offset.x < landmetric.x &&
				 offset.y >= 0 && offset.y < landmetric.y )
			{
				float height = tex2D(landscape,float2(offset.y/landmetric.y,offset.x/landmetric.x)).r*landmetric.z;
				if ( height >= offset.z )
					output.color = float4(1,1,1,1);
			}
		}
	}

    return output;
}

technique ComputeOcclusion
{
	pass P0
    {          
        VertexShader = compile vs_3_0 SimpleVS();
        PixelShader  = compile ps_3_0 RayTraycingPS(); 
    }
}

// ------------------------------------------------------------------------------------

float4 diffuse			 = float4( 0.1f, 0.6f, 0.2f, 1.0f );      
float3 lightDirection    = float3( 1.0f, 1.0f, 1.0f );		       
float4 lightDiffuse      = float4( 1.0f, 1.0f, 1.0f, 1.0f );      

float    time;                
float4x4 world;                  
float4x4 worldViewProjection;    

struct VSout
{
    float4 Position   : POSITION;   // vertex position 
    float4 Diffuse    : COLOR0;     // vertex diffuse color (note that COLOR0 is clamped from 0..1)
};

VSout RenderSceneVS( float4 vPos : POSITION, float3 vNormal : NORMAL )
{
    VSout output;
    float3 vNormalWorldSpace;
    output.Position = mul(vPos, worldViewProjection);
    vNormalWorldSpace = normalize(mul(vNormal, (float3x3)world));
    output.Diffuse.rgb = diffuse * lightDiffuse * max(0,dot(vNormalWorldSpace, lightDirection)) + diffuse*0.4;   
    output.Diffuse.a = 1.0f; 
    return output;    
}

VSout RenderLineVS( float4 pos : POSITION, float4 color : COLOR )
{
    VSout output;
    output.Position = mul(pos, worldViewProjection);
    output.Diffuse = color;
    return output;    
}

PSout RenderScenePS( VSout In ) 
{ 
    PSout output;
    output.color = In.Diffuse;
    return output;
}

technique RenderScene
{
    pass P0
    {          
        VertexShader = compile vs_2_0 RenderSceneVS();
        PixelShader  = compile ps_2_0 RenderScenePS(); 
    }
}

technique RenderSuperSphere
{
    pass P0
    {          
        VertexShader = compile vs_2_0 RenderSceneVS();
        PixelShader  = compile ps_2_0 RenderScenePS(); 
    }
}

technique RenderLine
{
    pass P0
    {          
        VertexShader = compile vs_2_0 RenderLineVS();
        PixelShader  = compile ps_2_0 RenderScenePS(); 
    }
}
